﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace FIS.iDET
{
    public class ImageService
    {
        string imageFileName;
        
        Bitmap tifImage;        
        
        int totalFrames, currentFrame;
        
        Boolean fileLoadedOK = true;

        public ImageService()
        {
            fileLoadedOK = false;
        }

        public ImageService(string imageFileName)
        {
            this.imageFileName = imageFileName;
            LoadTifFile();
        }

        public string FileName
        {
            get
            {
                return imageFileName;
            }
            set
            {
                imageFileName = value;
                LoadTifFile();
            }
        }

        public int TotalFrames
        {
            get
            {
                return totalFrames;
            }
            set
            {
                totalFrames = value;
            }
        }

        public int Width
        {
            get
            {
                return tifImage.Width;
            }
        }

        public int Height
        {
            get
            {
                return tifImage.Height;
            }
        }

        public int CurrentFrame
        {
            get
            {
                return currentFrame;
            }
            set
            {
                currentFrame = value;
            }
        }

        public Boolean FileLoadedOK
        {
            get
            {
                return fileLoadedOK;
            }
        }

        private void LoadTifFile()
        {
            try
            {
                // decode tif image into bitmap
                tifImage = new Bitmap(imageFileName);

                // get total number of pages
                totalFrames = tifImage.GetFrameCount(FrameDimension.Page);
            }
            catch
            {
                fileLoadedOK = false;
                MessageBox.Show("Cannot load image file, please check if it is a valid TIFF image.", "Invalid image", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private double zoomFactor = 1;
        
        public Bitmap GetImageZoom(double zoomFactor, DoubleRectangle rect)
        {
            // calculate Zoom size
            this.zoomFactor = zoomFactor;
            int zoomWidth = scaleUp(Width);
            int zoomHeight = scaleUp(Height);
            
            // create a new empty temporary bitmap
            Bitmap tmp = new Bitmap(zoomWidth, zoomHeight);
            // tmp.SetResolution(tifImage.HorizontalResolution, tifImage.VerticalResolution); //H.NH fix this

            // create new graphic object
            Graphics g = Graphics.FromImage(tmp);
            
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
            g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;

            // Zoom here
            Rectangle srcRect = new Rectangle(0, 0, Width, Height);
            Rectangle desRect = new Rectangle(0, 0, zoomWidth, zoomHeight);
            g.DrawImage(tifImage, desRect, srcRect, GraphicsUnit.Pixel);
                        // draw navigation guide
            if (rect.Width != 0 && rect.Y != 0)
            {
                float penStrokeWidth = (float)zoomFactor * 4;
                Pen penRed = new Pen(Color.Red, penStrokeWidth);
                Pen penOrange = new Pen(Color.Blue, penStrokeWidth);
                penRed.Alignment = System.Drawing.Drawing2D.PenAlignment.Outset;
                penOrange.Alignment = System.Drawing.Drawing2D.PenAlignment.Outset;
                Rectangle intRect= new Rectangle(0,0,0,0);
                intRect.X = scaleUp(rect.X);
                intRect.Y = scaleUp(rect.Y);
                intRect.Width = scaleUp(rect.Width);
                intRect.Height = scaleUp(rect.Height);
                if (rect.Width != 0 && rect.Height != 0)
                {
                    g.DrawLine(penOrange, 0, intRect.Y + intRect.Height, zoomWidth, intRect.Y + intRect.Height);
                    g.DrawLine(penOrange, intRect.X, 0, intRect.X, zoomHeight);
                }
                g.DrawRectangle(penRed, intRect);
            }

            // release Resource
            g.Dispose();
            // GC.Collect(); 
            return tmp;
        }

        public Bitmap GetImageZoom(double zoomFactor)
        {
            // calculate Zoom size
            this.zoomFactor = zoomFactor;
            int zoomWidth = scaleUp(Width);
            int zoomHeight = scaleUp(Height);

            // create a new empty temporary bitmap
            Bitmap tmp = new Bitmap(zoomWidth, zoomHeight);
            //tmp.SetResolution(tifImage.HorizontalResolution, tifImage.VerticalResolution);

            // create new graphic object
            Graphics g = Graphics.FromImage(tmp);

            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
            g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;

            // Zoom here
            Rectangle srcRect = new Rectangle(0, 0, Width, Height);
            Rectangle desRect = new Rectangle(0, 0, zoomWidth, zoomHeight);
            g.DrawImage(tifImage, desRect, srcRect, GraphicsUnit.Pixel);

            // release Resource
             g.Dispose();
            // GC.Collect();
            return tmp;
        }

        private int scaleUp(double original)
        {
            return (int) Math.Round(original * zoomFactor);
        }

        
        public void SetImageFrame(int frameToDisplay)
        {
            // var t1 = DateTime.Now;
            if (frameToDisplay >= 0 && frameToDisplay < totalFrames)
                currentFrame = frameToDisplay;
            // var t2 = DateTime.Now;
            // set active frame
            tifImage.SelectActiveFrame(FrameDimension.Page, currentFrame);
            // var t3 = DateTime.Now;
            //var t4 = DateTime.Now;

            //System.Diagnostics.Debug.WriteLine("time1: " + (t2.Subtract(t1).TotalMilliseconds.ToString()) +
            //        " time 2: " + (t3.Subtract(t2).TotalMilliseconds.ToString()) +
            //        " time 3: " + (t4.Subtract(t3).TotalMilliseconds.ToString()))
            //        ;
            //System.Diagnostics.Debug.WriteLine("finish");
        }
        
        
    }
}
